#include "lxz_config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lxz_types.h"
#include "os_port.h"
#include "lxz_runlog.h"
#include "lxz_debug.h"
#include "lxz_string.h"
#include "lxz_dbg_vmem.h"

/*
 *  Description:
 *    Get expected string from a specified string.
 *  Param: s, an ASCII string;
 *  Param: o, offsets
 *  Param: c, delimiter
 *  Param: buf, a buffer
 *  Return: p_ret_addr, NULL, fail;NON-NULL, success.
 *  History:
 */
char * lxz_string_f_strtok(const char * s, sint32 o, char c, char * buf)
{
    char * p_ret_addr = NULL;

    sint32 i = 0;
    sint32 i_str_len =0;

    if ((NULL == s) || (NULL == buf) || ('\0' == c))
    {
        return p_ret_addr;
    }

    i_str_len = strlen(s);
    i = o;
    while (i < i_str_len)
    {
        if (*(s+i) == c)
        {
            p_ret_addr = (char *)(s + i +1);
            break;
        }

        buf[i] = s[i];
        i++;
    }
    buf[i] = '\0';

    return p_ret_addr;
}

/*
 *  Description:
 *    UpCase all characters that in the specified string.
 *  Param: s, an ASCII string;
 *  Param: k, an octet character;
 *  Return: i_op_status, 0, fail;1, success.
 *  History:
 */
sint32 lxz_string_f_strkupcase(uint08 * s, uint08 k)
{
    sint32 i_op_status = 0;

    sint32 i = 0;
    sint32 i_str_len =0;

    if ((NULL == s))
    {
        return i_op_status;
    }

    while ('\0' != s[i])
    {
        if (k == s[i])
        {
            break;
        }

        if ((s[i] >= 'a') && (s[i] <= 'z'))
        {
            s[i] = s[i] - 'a' + 'A';
        }

        i++;
    }

    i_op_status = 1;
    return i_op_status;
}

/*
 *  Description:
 *    Get the first position of a specified character.
 *  Param: s, an ASCII string;
 *  Param: k, an octet character;
 *  Return: i_pos_keychar, -1, fail; >= 0, success.
 *  History:
 */
sint32 lxz_string_f_strkpos(const uint08 * s, char k)
{
    sint32 i_pos_keychar = -1;
    sint32 i = 0;
 
    if (NULL == s)
    {
        return i_pos_keychar;
    }
    
    while ('\0' != s[i])
    {
        if (k == s[i])
        {
            i_pos_keychar = i;
            break;
        }
        
        i++;
    }

    return i_pos_keychar;
}

/*
 *  Description:
 *    digital string or not.
 *  Param: s, an ASCII string;
 *  Param: l, length of string;
 *  Return: is_digital, 0, false; 1, true.
 *  History:
 */
sint32 lxz_string_f_isdigital(const uint08 * s, sint32 l)
{
    sint32 i_is_digital = 0;
    sint32 i = 0;
 
    if (NULL == s)
    {
        return i_is_digital;
    }
    
    i_is_digital = 1;
    while (i < l)
    {
        if ((s[i] < '0') || (s[i] > '9'))
        {
            break;
        }

        i++;
    }

    while (i < l)
    {
        if (s[i] != ' ')
        {
            i_is_digital = 0;
            break;
        }

        i++;
    }

    return i_is_digital;
}

/*
 *  Description:
 *    convert string.
 *  Param: s, an ASCII string;
 *  Param: l, length of string;
 *  Return: .
 *  History:
 */
char* lxz_string_f_strlwr(const char * s, sint32 l)
{
    sint32 i = 0;

    sint32 i_len_str = 0;
    char * p_cur_str = NULL;

    p_cur_str = (char *)s;
    if (NULL == p_cur_str)
    {
        return NULL;
    }

    i_len_str = l;
    if (0 == i_len_str)
    {
        i_len_str = strlen(p_cur_str);
    }

    while (i < i_len_str)
    {
        p_cur_str[i] = (char)(tolower(p_cur_str[i]) | 0x000000FF);
        i++;
    }

    return (char *)s;
}

/*
 *  Description:
 *    convert string.
 *  Param: s, an ASCII string;
 *  Param: l, length of string;
 *  Return: .
 *  History:
 */
char* lxz_string_f_strupr(const char * s, sint32 l)
{
    sint32 i = 0;

    sint32 i_len_str = 0;
    char * p_cur_str = NULL;

    p_cur_str = (char *)s;
    if (NULL == p_cur_str)
    {
        return NULL;
    }

    i_len_str = l;
    if (0 == i_len_str)
    {
        i_len_str = strlen(p_cur_str);
    }

    while (i < i_len_str)
    {
        p_cur_str[i] = toupper(p_cur_str[i]);
        i++;
    }

    return (char *)s;

}


/*
 *  Description:
 *    Converts the hex to bin.
 *  Param: hex_ptr, the hexadecimal format string;
 *  Param: length, the length of hexadecimal string;
 *  Param: bin_ptr, pointer to the binary format string;
 *  Return: FALSE, there's invalid character;
 *  Note: NONE
 */
sint32 lxz_string_f_hex2bin(const uint08 *hex_ptr, sint32 length, uint08 *bin_ptr)
{
    uint08        *dest_ptr = bin_ptr;
    sint32        i = 0;
    uint08        ch;

    for(i = 0; i < length; i += 2)
    {
        // the bit 8,7,6,5
        ch = hex_ptr[i];

        // digital 0 - 9
        if(ch >= '0' && ch <= '9')
        {
            *dest_ptr = (uint08)((ch - '0') << 4);
        }
        // a - f
        else if(ch >= 'a' && ch <= 'f')
        {
            *dest_ptr = (uint08)((ch - 'a' + 10) << 4);
        }
        // A - F
        else if(ch >= 'A' && ch <= 'F')
        {
            *dest_ptr = (uint08)((ch - 'A' + 10) << 4);
        }
        else
        {
            return 0;
        }

        // the bit 1,2,3,4
        ch = hex_ptr[i+1];

        // digtial 0 - 9
        if(ch >= '0' && ch <= '9')
        {
            *dest_ptr |= (uint08)(ch - '0');
        }
        // a - f
        else if(ch >= 'a' && ch <= 'f')
        {
            *dest_ptr |= (uint08)(ch - 'a' + 10);
        }
        // A - F
        else if(ch >= 'A' && ch <= 'F')
        {
            *dest_ptr |= (uint08)(ch - 'A' + 10);
        }
        else
        {
            return 0;
        }

        dest_ptr++;
    }

    return 1;

}

/*
 *  Description:
 *    Converts the bin to hex.
 *  Param: bin_ptr, the binary format string;
 *  Param: length, the length of hexadecimal string;
 *  Param: hex_ptr, pointer to the hexadecimal format string;
 *  Return: 1, success;
 *  Note: NONE
 */
sint32 lxz_string_f_bin2hex(const uint08 *bin_ptr, sint32 length, uint08 *hex_ptr)
{
    uint08        semi_octet;
    sint32        i;

    for(i = 0; i < length; i++)
    {
        // get the high 4 bits
        semi_octet = (uint08)((bin_ptr[i] & 0xF0) >> 4);

        if(semi_octet <= 9)  //semi_octet >= 0
        {
            *hex_ptr = (uint08)(semi_octet + '0');
        }
        else
        {
            *hex_ptr = (uint08)(semi_octet + 'A' - 10);
        }

        hex_ptr++;

        // get the low 4 bits
        semi_octet = (uint08)(bin_ptr[i] & 0x0f);

        if(semi_octet <= 9)  // semi_octet >= 0
        {
            *hex_ptr = (uint08)(semi_octet + '0');
        }
        else
        {
            *hex_ptr = (uint08)(semi_octet + 'A' - 10);
        }

        hex_ptr++;
    }

    return 1;
}

